package com.wongoing.util;

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Random;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
 * 功能说明：二维码生成工具类
 * 修改说明：
 * @author 吴兆强
 * @date 2017年12月14日 下午1:47:39
 * @version V0.1
 */
public class QRCodeUtil {
		private static final String CHARSET = "utf-8";  
	    private static final String FORMAT = "JPG";  
	    // 二维码尺寸  
	    private static final int QRCODE_SIZE = 300;  
	    // LOGO宽度  
	    private static final int LOGO_WIDTH = 60;  
	    // LOGO高度  
	    private static final int LOGO_HEIGHT = 60;  
	  
	    private static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {  
	        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();  
	        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);  
	        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);  
	        hints.put(EncodeHintType.MARGIN, 1);  
	        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,  
	                hints);  
	        int width = bitMatrix.getWidth();  
	        int height = bitMatrix.getHeight();  
	        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
	        for (int x = 0; x < width; x++) {  
	            for (int y = 0; y < height; y++) {  
	                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);  
	            }  
	        }  
	        if (logoPath == null || "".equals(logoPath)) {  
	            return image;  
	        }  
	        // 插入图片  
	        QRCodeUtil.insertImage(image, logoPath, needCompress);  
	        return image;  
	    }  
	  
	    /**
	     * 功能说明：插入图片  
	     * 修改说明：
	     * @author 吴兆强
	     * @date 2017年12月14日 下午1:48:44
	     * @param source 二维码图片 
	     * @param logoPath LOGO图片地址 
	     * @param needCompress 是否压缩 
	     * @throws Exception
	     */
	    private static void insertImage(BufferedImage source, String logoPath, boolean needCompress) throws Exception {  
	        File file = new File(logoPath);  
	        if (!file.exists()) {  
	            throw new Exception("logo file not found.");  
	        }  
	        Image src = ImageIO.read(new File(logoPath));  
	        int width = src.getWidth(null);  
	        int height = src.getHeight(null);  
	        if (needCompress) { // 压缩LOGO  
	            if (width > LOGO_WIDTH) {  
	                width = LOGO_WIDTH;  
	            }  
	            if (height > LOGO_HEIGHT) {  
	                height = LOGO_HEIGHT;  
	            }  
	            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);  
	            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
	            Graphics g = tag.getGraphics();  
	            g.drawImage(image, 0, 0, null); // 绘制缩小后的图  
	            g.dispose();  
	            src = image;  
	        }  
	        // 插入LOGO  
	        Graphics2D graph = source.createGraphics();  
	        int x = (QRCODE_SIZE - width) / 2;  
	        int y = (QRCODE_SIZE - height) / 2;  
	        graph.drawImage(src, x, y, width, height, null);  
	        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);  
	        graph.setStroke(new BasicStroke(3f));  
	        graph.draw(shape);  
	        graph.dispose();  
	    }  
	  
	    /** 
	     * 生成二维码(内嵌LOGO) 
	     * 二维码文件名随机，文件名可能会有重复 
	     *  
	     * @param content 
	     *            内容 
	     * @param logoPath 
	     *            LOGO地址 
	     * @param destPath 
	     *            存放目录 
	     * @param needCompress 
	     *            是否压缩LOGO 
	     * @throws Exception 
	     */  
	    public static String encode(String content, String logoPath, String destPath, boolean needCompress) throws Exception {  
	        BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);  
	        mkdirs(destPath);  
	        String fileName = new Random().nextInt(99999999) + "." + FORMAT.toLowerCase();  
	        ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));  
	        return fileName;  
	    }  
	      
	    /**
	     * 功能说明：sheng
	     * 修改说明：
	     * @author 吴兆强
	     * @date 2017年12月14日 下午2:15:23
	     * @param content
	     * @param logoPath
	     * @param destPath
	     * @param fileName
	     * @param needCompress
	     * @return
	     * @throws Exception
	     */
	    public static String encode(String content, String logoPath, String destPath, String fileName, boolean needCompress) throws Exception {  
	        BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);  
	        mkdirs(destPath);  
	        fileName = fileName.substring(0, fileName.indexOf(".")>0?fileName.indexOf("."):fileName.length())   
	                + "." + FORMAT.toLowerCase();  
	        ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));  
	        return fileName;  
	    }  
	  
	    /** 
	     * 当文件夹不存在时，mkdirs会自动创建多层目录，区别于mkdir． 
	     * (mkdir如果父目录不存在则会抛出异常) 
	     * @param destPath 
	     *            存放目录 
	     */  
	    public static void mkdirs(String destPath) {  
	        File file = new File(destPath);  
	        file.deleteOnExit();
	        if (!file.exists() && !file.isDirectory()) {  
	            file.mkdirs();  
	        }  
	    } 
	    
	    /**
	     * 功能说明：文件存在时建立
	     * 修改说明：
	     * @author 吴兆强
	     * @date 2017年12月18日 上午10:10:29
	     * @param destPath
	     */
	    public static void mkDirNoDelete(String destPath) {
	        File file = new File(destPath);  
	        if (!file.exists() && !file.isDirectory()) {  
	            file.mkdirs();  
	        } 
	    }
	  
	    /** 
	     * 生成二维码(内嵌LOGO) 
	     *  
	     * @param content 
	     *            内容 
	     * @param logoPath 
	     *            LOGO地址 
	     * @param destPath 
	     *            存储地址 
	     * @throws Exception 
	     */  
	    public static String encode(String content, String logoPath, String destPath) throws Exception {  
	        return QRCodeUtil.encode(content, logoPath, destPath, false);  
	    }  
	  
	    /** 
	     * 生成二维码 
	     *  
	     * @param content 
	     *            内容 
	     * @param destPath 
	     *            存储地址 
	     * @param needCompress 
	     *            是否压缩LOGO 
	     * @throws Exception 
	     */  
	    public static String encode(String content, String destPath, boolean needCompress) throws Exception {  
	        return QRCodeUtil.encode(content, null, destPath, needCompress);  
	    }  
	  
	    /** 
	     * 生成二维码 
	     *  
	     * @param content 
	     *            内容 
	     * @param destPath 
	     *            存储地址 
	     * @throws Exception 
	     */  
	    public static String encode(String content, String destPath) throws Exception {  
	        return QRCodeUtil.encode(content, null, destPath, false);  
	    }  
	  
	    /**
	     * 功能说明：二维码生成（服务器固定目录webapp/upload/img）
	     * 修改说明：
	     * @author 吴兆强
	     * @date 2017年12月18日 上午9:53:08
	     * @param content
	     * @return
	     * @throws Exception 
	     */
	    public static String encodeFixedPath(String content,String fileName) throws Exception {
	        BufferedImage image = QRCodeUtil.createImage(content, null, true);
	        String dirPath = ResourceUtil.getUploadImageRelativeRoot()+"qrcode";
	        mkDirNoDelete(dirPath);
	        fileName = fileName.contains(".") ? fileName : fileName + "." + FORMAT.toLowerCase();
	        String filePath = dirPath + "\\" + fileName;
	        File file = new File(filePath);  
	        file.deleteOnExit();  
	        boolean flag = ImageIO.write(image, FORMAT, new File(filePath));  
	        String relativePath = ResourceUtil.getUploadImgRelativeRoot()+"qrcode\\"+fileName;
	        return flag ? relativePath : Constants.ERROR;  
	    }
	    
		  
	/*    public static String encode(String content, String destPath, String fileName) throws Exception{
	    	  return QRCodeUtil.encode(content, null, destPath, fileName, false); 
	    }*/
	    
	    /** 
	     * 生成二维码(内嵌LOGO) 
	     *  
	     * @param content 
	     *            内容 
	     * @param logoPath 
	     *            LOGO地址 
	     * @param output 
	     *            输出流 
	     * @param needCompress 
	     *            是否压缩LOGO 
	     * @throws Exception 
	     */  
	    public static void encode(String content, String logoPath, OutputStream output, boolean needCompress)  
	            throws Exception {  
	        BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);  
	        ImageIO.write(image, FORMAT, output);  
	    }  
	  
	    /** 
	     * 生成二维码 
	     *  
	     * @param content 
	     *            内容 
	     * @param output 
	     *            输出流 
	     * @throws Exception 
	     */  
	    public static void encode(String content, OutputStream output) throws Exception {  
	        QRCodeUtil.encode(content, null, output, false);  
	    }  

	    
	    /** 
	     * 解析二维码 
	     *  
	     * @param file 
	     *            二维码图片 
	     * @return 
	     * @throws Exception 
	     */  
	    public static String decode(File file) throws Exception {  
	        BufferedImage image;  
	        image = ImageIO.read(file);  
	        if (image == null) {  
	            return null;  
	        }  
	        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);  
	        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));  
	        Result result;  
	        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();  
	        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);  
	        result = new MultiFormatReader().decode(bitmap, hints);  
	        String resultStr = result.getText();  
	        return resultStr;  
	    }  
	  
	    /** 
	     * 解析二维码 
	     *  
	     * @param path 
	     *            二维码图片地址 
	     * @return 
	     * @throws Exception 
	     */  
	    public static String decode(String path) throws Exception {  
	        return QRCodeUtil.decode(new File(path));  
	    }  
	  
	   /* public static void main(String[] args) throws Exception {  
	        String text = "http://www.baidu.com";  
	        //不含Logo  
	        //QRCodeUtil.encode(text, null, "e:\\", true);  
	        //含Logo，不指定二维码图片名  
	        //QRCodeUtil.encode(text, "e:\\csdn.jpg", "e:\\", true);  
	        //含Logo，指定二维码图片名  
	        QRCodeUtil.encode(text, "e:\\csdn.jpg", "e:\\", "qrcode", true);  
	    }  */
}
